<?php
namespace Tlf\Scrawl\Ext\DefaultExt;
/**
* Runs `@mdverb` extensions, enabling special callbacks for `@verb()`s in `.src.md` files
*/
class MarkdownVerbs extends \Tlf\Scrawl\ExtensionType\DefaultExt {
protected $regData = [
'verb' =>'/(?<!\\\\)\@([a-zA-Z_]+)\(([^\)]*)\)/m',
];
/**
* Array mapping verbs to callables `['verb'=>[ $callable1, $callable2, $callable3], 'anotherverb'=>[...] ]`
*/
protected array $verbMap = [];
/**
* Setup the verb map
*/
public function onBuildStart(){
$exts = $this->scrawl->getExtensions('mdverb');
foreach ($exts as $ext){
$verbs = $ext->getVerbs();
foreach ($verbs as $verb=>$method){
$this->verbMap[$verb][] = [$ext, $method];
}
}
}
/**
* Find verbs in a source md file
*/
public function onTemplateFileFound(\Tlf\Scrawl\File $templateFile){
$this->match('verb',$templateFile,$templateFile);
$this->writeMdFile($templateFile);
}
/**
* Execute md verb extension methods & update output-content
*/
public function matchVerb($info, $templateFile, $verb, $argListStr){
$file = $templateFile;
$line = $info['match'][0];
$parsedArgs = $this->parseArgListString($argListStr);
$info = [
'file'=>$file,
'line'=>$line,
'verb'=>$verb,
'argListStr'=>$argListStr,
'argList' => $parsedArgs,
];
foreach ($this->verbMap[$verb]??[] as $callable){
// $ret = $callable($verb, $argListStr, $file, $line);
try {
$ret = $callable($info, ...$parsedArgs);
} catch (\ArgumentCountError $e){
$class = get_class($callable[0]);
$method = $callable[1];
echo "\n\n";
echo "\nCannot call $class->$method() becuase of an argument count error.";
echo "\n\n";
echo "Error caused by: \n";
$info = (array)$info;
$info['file'] = (array)$info['file'];
$info['file']['content'] = '--content is removed from var dump for readability--';
print_r($info);
echo "\n\n";
throw $e;
}
if ($ret===false)continue;
$file->content = str_replace($line, $ret, $file->content());
}
}
/**
* Append the correct md file to the output, to later be written by Scrawl
*/
public function writeMdFile(\Tlf\Scrawl\File $templateFile){
$relPath = $templateFile->relPath;
$ext = '.src.md';
$len = strlen($ext);
if (substr($relPath, -$len)==$ext){
$relPath = substr($relPath,0,-$len).'.md';
}
if ($this->scrawl->getConfig('markdown.preserveNewLines')[0]){
// @TODO add test for markdown.preserveNewLines
$templateFile->content = str_replace("\n"," \n",$templateFile->content());
}
if ($this->scrawl->getConfig('markdown.prependGenNotice')[0]){
// @TODO give relative path to source file
$templateFile->content = "<!-- DO NOT EDIT. This file generated from template by Code Scrawl https://tluf.me/code-scrawl/ -->\n".$templateFile->content();
}
$templateDir = $this->scrawl->getConfig('dir.template')[0];
$this->scrawl->addOutput('file', $relPath, $templateFile->content());
}
/**
* Parse an arg list string & return it as an array
*
* Each arg is trimmed. There is no special handling of any character. Commas may not appear in arguments, as they are argument separators.
*
* @param $argListString a string like `arg1, arg2, arg3` where every arg is separated by a comma.
*
*/
public function parseArgListString(string $argListString): array{
$list = explode(',', $argListString);
$list = array_map('trim', $list);
return $list;
}
}